package cn.xianyang.basic.service.impl;

import cn.xianyang.basic.constants.BaseConstant;
import cn.xianyang.basic.dto.EmailRegisterDto;
import cn.xianyang.basic.dto.RegisterDto;
import cn.xianyang.basic.exception.BusinessException;
import cn.xianyang.basic.service.IVerifyCodeService;
import cn.xianyang.basic.util.MailSenderUtils;
import cn.xianyang.basic.util.StrUtils;
import cn.xianyang.basic.util.VerifyCodeUtils;
import cn.xianyang.user.domain.User;
import cn.xianyang.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    //注入redis
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String imageCodeKey(String key) {
        //如果没有长度
        if (!StringUtils.hasLength(key)) {
            throw new BusinessException("key不能为空！");
        }
        String code = StrUtils.getComplexRandomString(4);//生成code
        System.out.println(key);
        System.out.println(code);
        //保存redis设置过期时间key前端传递的UUID,code前端传递的编码,TimeUnit.MINUTES单位过期时间5分钟
        redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
        //使用2d引擎把code化成图，图使用base64编成字符串，最后返回字符串
        return VerifyCodeUtils.VerifyCode(100, 40, code);
    }

    /**
     * 发送短信验证码一系列逻辑
     *
     * @param dto
     */
    @Override
    public void smsCode(RegisterDto dto) {
        //1参数空校验
        String phone = dto.getPhone();
        String imageCodeValue = dto.getImageCodeValue();
        String imageCodeKey = dto.getImageCodeKey();
        //如果参数为空就异常
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(imageCodeValue) || StringUtils.isEmpty(imageCodeKey)) {
            throw new BusinessException("不好意思,您输入的参数异常");
        }
        //2校验图形验证码，根据imageCodeKey从redis中获取图形验证码
        Object imageCodeTmp = redisTemplate.opsForValue().get(imageCodeKey);
        //获取不到，重新获取，因为已经过期了
        if (imageCodeTmp == null) {
            throw new BusinessException("不好意思,验证码已过期,请重新获取");
        }
        //获取到，比较图形验证码，不要区分大小写
        //如果正确就执行下一步
        if (!imageCodeTmp.toString().equalsIgnoreCase(imageCodeValue)) {
            //不正确就直接报错提醒
            throw new BusinessException("请输入正确的验证码");
        }
        //3校验手机号是否注册过  查询user表
        User userTmp = userMapper.loadByPhone(phone);
        //已经注册过提醒登录
        if (userTmp != null) {
            throw new BusinessException("用户已存在，请直接登录");
        } //没有注册过就往下执行
        //4 短信验证码根据手机号拼接key，register：185 ，从redis中获取曾经可能发送的短信验证码
        String key = BaseConstant.RegisterConstants.REGISTER_SMS_PREFIX + phone;
        //查询redis
        Object smsCodeTmp = redisTemplate.opsForValue().get(key);
        //获取到了
        String smsCode = "";
        if (smsCodeTmp != null) {
            //校验是否过了一分钟重发时间value   ,因为对象是Obj所以要用tosStirng
            Long oldTmp = Long.valueOf(smsCodeTmp.toString().split(":")[1]);//上一次发送验证码的时间
            if (System.currentTimeMillis() - oldTmp <= 1 * 60 * 1000) {
                //如果小于一分钟就是有人跳过前端zaigaoshi
                throw new BusinessException("别乱来哈，小姐妹");
            }
            //大于一分钟 （但是还在验证码有效期3分内）.使用还没过期的验证码，刷新过期时间！！！！！
            smsCode = smsCodeTmp.toString().split(":")[0];
        } else {
            //获取不到，生成新的短信验证码
            smsCode = StrUtils.getComplexRandomString(4);
        }
        //存储redis设置一个过期时间 + 加上当前时间戳
        String smsCodeValue = smsCode + ":" + System.currentTimeMillis();
        redisTemplate.opsForValue().set(key, smsCodeValue, 3, TimeUnit.MINUTES);
        //发送短信
//      SmsUtils.senSms(phone,"亲，您的验证码是:"+ smsCode + "。请在三分钟内使用");
        System.out.println("亲，您的验证码是:" + smsCode + "。请在三分钟内使用");

    }

    /**
     * 发送邮箱验证码
     *
     * @param dto
     */
    @Override
    public void emailCode(EmailRegisterDto dto) {
        String email = dto.getEmail();
        String imageCodeKey = dto.getImageCodeKey();
        String imageCodeValue = dto.getImageCodeValue();
        //1.非空校验
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(imageCodeKey) || StringUtils.isEmpty(imageCodeValue)) {
            throw new BusinessException("参数不能为空");
        }
        String emailCodekey = BaseConstant.RegisterConstants.REGISTER_SMS_PREFIX + email;
        String valueTemp = (String) redisTemplate.opsForValue().get(emailCodekey);
        if (valueTemp == null) {
            //如果没有查询到数据 那么就生成一份
            valueTemp = StrUtils.getComplexRandomString(5);
        } else {
            //如果查询到了 说明数据还在 判断是否间隔上次获取时间过了一分钟 55555:1231231212312
            if (System.currentTimeMillis() - Long.valueOf(valueTemp.split(":")[1]) < 60 * 1000) {
                throw new BusinessException("系统繁忙,请稍后再获取邮箱验证码!");
            }
            //如果过了就使用之前的验证码
            valueTemp = valueTemp.split(":")[0];
            //保存数据到redis
            redisTemplate.opsForValue().set(
                    emailCodekey,
                    valueTemp + ":" + System.currentTimeMillis(),
                    3,
                    TimeUnit.MINUTES

            );
            //发送邮箱验证码
            MailSenderUtils.simpleSend(email, "宠物之家:", "尊敬的用户,您的注册邮箱验证码是: " + valueTemp);
        }
    }
}





















